(function() {
	var regEnumMethod = jMass.regEnumMethod;

	regEnumMethod("toArray", function() {
		var enumerator = this.toEnum();
		enumerator.reset();
		var res = [];
		while (enumerator.next())
			res.push(enumerator.current);
		return res;
	});

	regEnumMethod("toList", function() {
		return new jMass.List(this.toArray());
	});

	regEnumMethod("contains", function(clause) {
		var enumerator = this.toEnum();
		enumerator.reset();
		var where = baseEnum_getClause(clause);
		if (!where)
			return enumerator.next();
		while (enumerator.next()) {
			if (where(enumerator.current))
				return true;
		}
		return false;
	});

	regEnumMethod("each", function(iteratorFunc, repeat) {
		var enumerator = this.toEnum();
		iteratorFunc = baseEnum_getClause(iteratorFunc);
		repeat = repeat || 1;
		while (repeat-- > 0) {
			enumerator.reset();
			while (enumerator.next())
				iteratorFunc(enumerator.current);
		}
	});

	regEnumMethod("first", function(clause) {
		var enumerator = this.toEnum();
		this.reset();
		clause = baseEnum_getClause(clause);
		if (!clause) {
			enumerator.next();
			return enumerator.current;
		}
		while (enumerator.next()) {
			if (clause(enumerator.current)) {
				return enumerator.current;
			}
		}
		return null;
	});

	regEnumMethod("firstOrDefault", function(clause, defaultIfEmpty) {
		var first;
		return (first = this.toEnum().first(clause)) ? first : defaultIfEmpty;
	});

	regEnumMethod("last", function(clause) {
		var result, enumerator = this.toEnum();
		enumerator.reset();
		clause = baseEnum_getClause(clause);
		if (!clause) {
			while (enumerator.next())
				result = enumerator.current;

		} else {
			while (enumerator.next()) {
				if (clause(enumerator.current))
					result = enumerator.current;
			}
		}
		return result;
	});

	regEnumMethod("lastOrDefault", function(clause, defaultIfEmpty) {
		var last;
		return (last = this.toEnum().last(clause)) ? last : defaultIfEmpty;
	});

	regEnumMethod("sum", function(clause) {
		var result = 0, itemValue = 0, enumerator = this.toEnum();
		enumerator.reset();
		clause = baseEnum_getClause(clause, default_clauses_returnCurrent);
		while (enumerator.next())
			result += (itemValue = clause(enumerator.current)) ? itemValue : 0;
		return result;
	});

	regEnumMethod("avg", function(clause) {
		var sum = 0, count = 0, itemValue = 0, enumerator = this.toEnum();
		clause = baseEnum_getClause(clause, default_clauses_returnCurrent);
		enumerator.reset();
		while (enumerator.next()) {
			itemValue = clause(enumerator.current);
			if (itemValue !== null) {
				sum += itemValue;
				count++;
			}
		}
		return count === 0 ? 0 : sum / count;
	});

	regEnumMethod("max", function(clause) {
		var result, enumerator = this.toEnum();
		enumerator.reset();
		if (!enumerator.next())
			return 0;
		clause = baseEnum_getClause(clause, default_clauses_returnCurrent);
		result = clause(enumerator.current);
		while (enumerator.next())
			result = Math.max(result, clause(enumerator.current));
		return result;
	});

	regEnumMethod("min", function(clause) {
		var result, enumerator = this.toEnum();
		enumerator.reset();
		if (!enumerator.next())
			return 0;
		clause = baseEnum_getClause(clause, default_clauses_returnCurrent);
		result = clause(enumerator.current);
		while (enumerator.next())
			result = Math.min(result, clause(enumerator.current));
		return result
	});

	regEnumMethod("count", function(condiction) {
		var result = 0, enumerator = this.toEnum();
		condiction = baseEnum_getClause(condiction, null);
		enumerator.reset();
		if (!condiction) {
			for (; enumerator.next(); result++) {
			}
		} else {
			while (enumerator.next()) {
				if (condiction(enumerator.current))
					result++;
			}
		}
		return result;
	});
	
	regEnumMethod("any", function(condiction) {
		var enumerator = this.toEnum();
		condiction = baseEnum_getClause(condiction, "x => true");
		enumerator.reset();
		while(enumerator.next()){
			if (condiction(enumerator.current))
				return true;
		}
		return false;
	});
})();
